/**
* \file DGVFile.h
*
* \brief This file defines the class for reading and writing data as text files with or without comments using only Qt.
* \author Shekhar S. Chandra, 2008-2009
*
* This file is part of DGV Library.
*
* DGV is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* DGV is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with DGV.  If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef DGVFILE_H
#define DGVFILE_H

#include "DGVAliases.h"

#include <QFile>
#include <QTextStream>
#include <QStringList>

/*!
    \class DGVFile
    \brief This class handles reading and writing of files with comments using Qt.
    \author Shekhar S. Chandra, 2008-2009

    It is mainly used to read/write CSV and Diophantine (to setup a system using DGVLatticeVTK and DGVDiophantineVTK classes) files.

    Mode needs to be set for the operation that needs to be done. Mode is either "r" for read, "w" for write or "a" for append.
*/
class DGV_EXPORT DGVFile
{
public:
    /**
    \fn DGVFile::DGVFile()
    \brief Constructor
    */
    DGVFile();
    /**
    \fn DGVFile::DGVFile()
    \brief Constructor with filename and mode pass in. Mode is either "r" for read, "w" for write or "a" for append.

    Equivalent to calling open().
    */
    DGVFile(QString name, QString mode);
    virtual ~DGVFile();

    /**
    \fn DGVFile::open(QString name, QString mode)
    \brief Open file with filename. Mode is either "r" for read, "w" for write or "a" for append.
    */
    bool open(QString name, QString mode);
    /**
    \fn DGVFile::close()
    \brief Close the current file.
    */
    void close();

    /**
    \fn DGVFile::writeLine(QString data)
    \brief Write the line given by "data" to the current file.
    */
    void writeLine(QString data);
    /**
    \fn DGVFile::writeIntegerArrayAsLine(Array<long,1> &data)
    \brief Write the line given by the array "data" to the current file.
    */
    void writeIntegerArrayAsLine(Array<long,1> &data);
    /**
    \fn DGVFile::writeDoubleArrayAsLine(Array<double,1> &data)
    \brief Write the line given by the array "data" to the current file.
    */
    void writeDoubleArrayAsLine(Array<double,1> &data);
    /**
    \fn DGVFile::writeComment(QString comment)
    \brief Write the comment to the current file.
    */
    void writeComment(QString comment);
    /*void writeIntegerArray(Array<int,1> &data);
    void writeArray(Array<imageType,1> &data);
    void writeArray(Array<imageType,2> &data);*/
    //void writeArrayAsCSV(Array<>);
    /**
    \fn DGVFile::readNextString()
    \brief Read the next element as a string from the current file. NOT IMPLEMENTED!
    \todo Implement read string member
    */
    QString readNextString();
    /**
    \fn DGVFile::readNextInteger()
    \brief Read the next element as an integer from the current file. NOT IMPLEMENTED!
    \todo Implement read int member
    */
    long readNextInteger();
    /**
    \fn DGVFile::readNextDouble()
    \brief Read the next element as an double from the current file. NOT IMPLEMENTED!
    \todo Implement read double member
    */
    double readNextDouble();
    /**
    \fn DGVFile::readLine()
    \brief Read the next line as a string list from the current file.
    Same as readNextLine().
    */
    inline QStringList readLine()
    {   return readNextLine(); }
    /**
    \fn DGVFile::readNextLine()
    \brief Read the next line as a string list from the current file.
    */
    QStringList readNextLine();
    /**
    \fn DGVFile::readNextLineAsIntegers(Array<long,1> &values)
    \brief Read the next line as a integer list from the current file. Array is automatically resized to correct size.
    */
    void readNextLineAsIntegers(Array<long,1> &values);
    /**
    \fn DGVFile::readNextLineAsDoubles(Array<double,1> &values)
    \brief Read the next line as a double list from the current file. Array is automatically resized to correct size.
    */
    void readNextLineAsDoubles(Array<double,1> &values);

    /**
    \fn DGVFile::setSeparator(QString symbol)
    \brief Set the separator of the data in the current file.
    */
    inline void setSeparator(QString symbol)
    {   separator = symbol;     }
    /**
    \fn DGVFile::setCommentSymbol(QString symbol)
    \brief Set the comment symbol of the data in the current file.
    */
    inline void setCommentSymbol(QString symbol)
    {   commentSymbol = symbol; }
    /**
    \fn DGVFile::ignoreComments(bool ignore)
    \brief Ignore comments in the current file. Default is true.
    */
    inline void ignoreComments(bool ignore)
    {   comments = ignore;  }

    /**
    \fn DGVFile::atEnd()
    \brief Return true if the end of the current file is reached.
    */
    bool atEnd();
    /**
    \fn DGVFile::setVerboseMode(bool verbose)
    \brief Read as much of the file as possible. Useful in comment ignore mode if file has empty entries.
    */
    inline void setVerboseMode(bool verbose)
    {   verboseMode = verbose;  }

protected:
    QString commentSymbol;
    QString separator;
    bool comments;
    bool openedIn;
    bool openedOut;
    bool openedAppend;
    bool verboseMode;
    QString fileName;
    QString fileMode;

    QFile file;
    QTextStream *in;
    QTextStream *out;
    QTextStream *append;
};

#endif // DGVFILE_H
